package cn.com.bluemoon.daps.system.service.impl;

import cn.com.bluemoon.daps.common.domain.FeignApiRespBean;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.domp.api.LocalDompService;
import cn.com.bluemoon.daps.domp.api.UserService;
import cn.com.bluemoon.daps.domp.api.param.RoleDto;
import cn.com.bluemoon.daps.domp.api.param.UserDto;
import cn.com.bluemoon.daps.system.entity.DapSysMenu;
import cn.com.bluemoon.daps.system.entity.DapSysRoleMenu;
import cn.com.bluemoon.daps.system.entity.DapSysUser;
import cn.com.bluemoon.daps.system.entity.DapSysUserRole;
import cn.com.bluemoon.daps.system.service.DapSysMenuService;
import cn.com.bluemoon.daps.system.service.DapSysRoleMenuService;
import cn.com.bluemoon.daps.system.service.DapSysUserRoleService;
import cn.com.bluemoon.daps.system.service.DapSysUserService;
import cn.com.bluemoon.daps.system.utils.JwtUtils;
import cn.com.bluemoon.daps.system.utils.SecurityUtils;
import cn.com.bluemoon.dataserver.common.dto.JwtDTO;
import cn.com.bluemoon.metadata.common.exception.DescribeException;
import com.auth0.jwt.interfaces.Claim;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Lilike on 2023/1/2
 */
@Service
public class LocalDompServiceImpl   {

    @Autowired
    private DapSysUserService dapSysUserService;

    @Autowired
    private DapSysUserRoleService dapSysUserRoleService;

    @Autowired
    private DapSysRoleMenuService dapSysRoleMenuService;

    @Autowired
    private DapSysMenuService dapSysMenuService;

    public FeignApiRespBean<String> dompLogin(String userId, String password, String validationCode) {
        DapSysUser one = dapSysUserService.lambdaQuery().eq(DapSysUser::getAccount, userId).one();
        if (one == null) {
            throw new DescribeException("用户名或密码错误",ResultBean.FAIL_CODE);
        }

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String securityPwd = "{bcrypt}" + passwordEncoder.encode(password);
        if (passwordEncoder.matches(password,one.getPassword().substring("{bcrypt}".length()))) {
            // 生成token
            Map<String,Object> userAccountInfoMap = new HashMap<>();
            userAccountInfoMap.put(JwtUtils.USER_NAME,one.getUserName());
            userAccountInfoMap.put(JwtUtils.ACCOUNT,one.getAccount());
            JwtDTO token = JwtUtils.createToken(userAccountInfoMap);
            FeignApiRespBean<String> res = new FeignApiRespBean<>();
            res.setToken(token.getXToken());
            res.setRespCode("200");
            return res;
        }
        throw new DescribeException("用户名或密码错误",ResultBean.FAIL_CODE);
    }


    public Map<String, List<LocalDompService.MenuDto>> getMenuPathByTokenAndUserId(String token, String userId) {
        Map<String, Claim> verifyToken = JwtUtils.verifyToken(token);
        if (verifyToken == null) {
            throw new DescribeException("token失效",ResultBean.FAIL_CODE);
        }
        String account = verifyToken.get(JwtUtils.ACCOUNT).asString();

        DapSysUser one = dapSysUserService.lambdaQuery().eq(DapSysUser::getAccount, account).one();
        List<DapSysUserRole> roles = dapSysUserRoleService.lambdaQuery().eq(DapSysUserRole::getUserId, one.getId()).list();
        if (CollectionUtils.isNotEmpty(roles)) {
            List<Long> roleIds = roles.stream().map(x -> x.getRoleId()).collect(Collectors.toList());
            List<DapSysRoleMenu> list = dapSysRoleMenuService.lambdaQuery().in(DapSysRoleMenu::getRoleId, roleIds).list();
            List<Long> menuIds = list.stream().map(x -> x.getMenuId()).collect(Collectors.toList());
            List<DapSysMenu> menus = dapSysMenuService.lambdaQuery().in(DapSysMenu::getId, menuIds).list();

            Set<Long> parentIdSet = menus.stream().filter(x -> x.getParentId() != 0).map(x -> x.getParentId()).collect(Collectors.toSet());

            int i = 1;
            while (!parentIdSet.isEmpty()) {
                // 获取到父菜单
                i++;
                List<DapSysMenu> parentMenuList = dapSysMenuService.lambdaQuery().in(DapSysMenu::getId, parentIdSet).list();
                menus.addAll(parentMenuList);
                parentIdSet = menus.stream().filter(x -> x.getParentId() != 0).map(x -> x.getParentId()).collect(Collectors.toSet());
                if ( i > 10) {
                    break;
                }
            }

            List<LocalDompService.MenuDto> menuDtos = menus.stream().map(x -> {
                LocalDompService.MenuDto menuDto = new LocalDompService.MenuDto();
                menuDto.setMenu_sort(x.getSort());
                menuDto.setMenu_control("1");
                menuDto.setMenu_des(x.getRemarks());
                menuDto.setMenu_level("1");
                menuDto.setMenu_name(x.getName());
                menuDto.setMenu_path(x.getUrl());
                menuDto.setStatus("1");
                menuDto.setMenu_parent_id(x.getParentId().intValue());
                return menuDto;
            }).collect(Collectors.toList());
            return menuDtos.stream().collect(Collectors.groupingBy(x -> x.getMenu_path() ));
        }

        return null;
    }


    public ResultBean<List<UserDto>> matchUserInfos(String token, String tecName, Object o) {
        List<DapSysUser> list = dapSysUserService.lambdaQuery().like(DapSysUser::getUserName, tecName).list();
        List<UserDto> collect = list.stream().map(x -> {
            UserDto userDto = new UserDto();
            userDto.setUser_name(x.getUserName());
            userDto.setMobile(x.getMobile());
            userDto.setId(x.getAccount());
            userDto.setStatus(x.getIsUse() + "");
            return userDto;
        }).collect(Collectors.toList());
        ResultBean<List<UserDto>> data = ResultBean.data(ResultBean.SUCCESS_CODE, collect);
        return data;
    }
}
